package jnpf.engine.util;

import cn.hutool.core.util.ObjectUtil;
import jnpf.config.ConfigValueUtil;
import jnpf.database.model.dto.PrepareSqlDTO;
import jnpf.database.model.entity.DbLinkEntity;
import jnpf.database.util.ConnUtil;
import jnpf.database.util.DataSourceUtil;
import jnpf.database.util.JdbcUtil;
import jnpf.exception.DataException;
import jnpf.model.visiual.JnpfKeyConsts;
import jnpf.model.visiual.TableModel;
import jnpf.model.visiual.fields.FieLdsModel;
import jnpf.util.JsonUtil;
import jnpf.util.StringUtil;
import jnpf.util.UserProvider;
import jnpf.util.context.SpringContext;
import lombok.Cleanup;
import org.apache.commons.lang3.StringUtils;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 验证表单数据
 *
 * @author JNPF开发平台组
 * @version V3.4.2
 * @copyright 引迈信息技术有限公司（https://www.jnpfsoft.com）
 * @date 2022/5/25
 */
public class OnlineDevFormUtils {

    private static DataSourceUtil dataSourceUtil;
    private static ConfigValueUtil configValueUtil;
    private static UserProvider userProvider;
    private static FlowDataUtil flowDataUtil = SpringContext.getBean(FlowDataUtil.class);

    /**
     * 初始化
     */
    public static void init() {
        configValueUtil = SpringContext.getBean(ConfigValueUtil.class);
        userProvider = SpringContext.getBean(UserProvider.class);
        dataSourceUtil = SpringContext.getBean(DataSourceUtil.class);
    }

    public static boolean checkForm(List<FieLdsModel> formFieldList, Map<String, Object> dataMap, DbLinkEntity linkEntity, List<TableModel> tableModelList, Integer policy, String id) {
        //查询返回对应条数
        int i = 0;
        List<PrepareSqlDTO> allSql = new ArrayList<>();
        //符合条件的控件
        List<FieLdsModel> mainFields = checkInputUnique(formFieldList);
        try {
            //数据源
            @Cleanup Connection conn = getDataConn(linkEntity);
            for (FieLdsModel fieLdsModel : mainFields) {
                Object o = dataMap.get(fieLdsModel.getVModel());
                if (ObjectUtil.isNotNull(o) && StringUtil.isNotEmpty(o.toString())) {
                    String tableName = fieLdsModel.getConfig().getTableName();
                    String sql = "SELECT COUNT(*) FROM " + tableName + " WHERE " + fieLdsModel.getVModel() + "= '" + o.toString() + "'";
                    if (StringUtils.isNotEmpty(id)){
                        String relationField;
                        //判断是否主表
                        TableModel tab = tableModelList.stream().filter(tableModel -> tableModel.getTable().equalsIgnoreCase(tableName)).findFirst().orElse(null);
                        if ("1".equals(tab.getTypeId())){
                            relationField = flowDataUtil.getKey(conn,tableName,policy);
                        }else {
                            relationField = tab.getTableField();
                        }
                        sql = sql + " AND " + relationField + " != '" + id + "'";
                    }
                    PrepareSqlDTO dto = new PrepareSqlDTO(conn, sql);
                    allSql.add(dto);
                }
            }

            List<FieLdsModel> childFieldList = formFieldList.stream().filter(f -> JnpfKeyConsts.CHILD_TABLE.equals(f.getConfig().getJnpfKey())).collect(Collectors.toList());
            for (FieLdsModel fieLdsModel : childFieldList) {
                List<FieLdsModel> fieLdsModels = checkInputUnique(fieLdsModel.getConfig().getChildren());
                List<Map<String, Object>> childMapList = JsonUtil.getJsonToListMap(String.valueOf(dataMap.get(fieLdsModel.getVModel())));
                if (childMapList!=null){
                    for (FieLdsModel childField : fieLdsModels) {
                        List<String> childValues = childMapList.stream().filter(ChildTbMap -> ChildTbMap.get(childField.getVModel())!=null)
                            .map(ChildTbMap -> String.valueOf(ChildTbMap.get(childField.getVModel()))).collect(Collectors.toList());

                        if (childValues.size() > 0) {
                            HashSet<String> child = new HashSet<>(childValues);
                            if (child.size() != childValues.size()){
                                i++;
                            }
                            String tableName = childField.getConfig().getRelationTable();
                            String collect = childValues.stream().map(c -> "'" + c + "'").collect(Collectors.joining(","));
                            String sql = "SELECT COUNT(*) FROM " + tableName + " WHERE " + childField.getVModel() + " in ( " + collect + ")";
                            if (StringUtils.isNotEmpty(id)){
                                String relationField;
                                //判断是否主表
                                TableModel tab = tableModelList.stream().filter(tableModel -> tableModel.getTable().equalsIgnoreCase(tableName)).findFirst().orElse(null);
                                relationField = tab.getTableField();
                                sql = sql + " AND " + relationField + " != '" + id + "'";
                            }
                            PrepareSqlDTO dto = new PrepareSqlDTO(conn, sql);
                            allSql.add(dto);
                        }
                    }
                }
            }


            for (PrepareSqlDTO dto : allSql) {
                Integer integer = Integer.valueOf(String.valueOf(JdbcUtil.queryOne(dto).get("COUNT(*)")));
                if (integer > 0 ) {
                    i++;
                }
            }
            if (conn != null) {
                conn.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (i > 0) {
            return false;
        }
        return true;
    }

    /**
     * 输入框唯一
     *
     * @param fields
     * @return
     */
    private static List<FieLdsModel> checkInputUnique(List<FieLdsModel> fields) {
        List<FieLdsModel> inputUnique = fields.stream().filter(field -> JnpfKeyConsts.COM_INPUT.equals(field.getConfig().getJnpfKey())
                && field.getConfig().getUnique()).collect(Collectors.toList());
        return inputUnique;
    }


    public static Connection getDataConn(DbLinkEntity linkEntity) throws SQLException {
        Connection conn = null;
        if (linkEntity != null) {
            try {
                conn = ConnUtil.getConn(linkEntity);
            } catch (DataException e) {
                e.printStackTrace();
            }
        } else {
            conn = getTableConn();
        }
        if (conn == null) {
            throw new SQLException("连接数据库失败");
        }
        return conn;
    }

    /**
     * 获取有表的数据库连接
     *
     * @return
     */
    public static Connection getTableConn() {
        init();
        String tenId;
        if (!configValueUtil.isMultiTenancy()) {
            tenId = dataSourceUtil.getDbName();
        } else {
            if (!"PostgreSQL".equals(dataSourceUtil.getDbType())) {
                tenId = userProvider.get().getTenantDbConnectionString();
            } else {
                tenId = dataSourceUtil.getDbName();
            }
        }
        try {
            return ConnUtil.getConn(dataSourceUtil, tenId);
        } catch (DataException e) {
            e.printStackTrace();
        }
        return null;
    }


}
